# -*- coding:utf-8 -*-
"""Created By Corvo"""

from functools import wraps

from mod.common.minecraftEnum import TimeEaseType

from const import *
from ..system.base import *

if __name__ == '__main__':
    from server import VirtualModuleServer


def is_active_virtual(func):
    @wraps(func)
    def wrapped(*args, **kwargs):
        module = args[0]  # type: VirtualModuleClient
        if not module.is_visible:
            return
        func(*args, **kwargs)

    return wrapped


class VirtualModuleClient(ModuleClientBase):
    """虚拟世界模块客户端"""
    __mVersion__ = 1
    __identifier__ = ModuleEnum.identifier

    def __init__(self):
        super(VirtualModuleClient, self).__init__()
        self.virtual_comp = self.comp_factory.CreateVirtualWorld(clientApi.GetLevelId())
        self.rpc = self.ModuleSystem.CreateRpcModule(self, ModuleEnum.identifier)

        self.entity_storage = {}
        # 相机位置
        self.camera_pos = [0, 0, 0]
        self.camera_step = 1.0

        self.is_visible = None  # 是否虚拟世界显示
        self.is_moving_camera = False  # 是否正在移动相机

        self.virtual_comp.VirtualWorldCreate()
        self.SetVisible(False)

    def OnDestroy(self):
        self.virtual_comp.VirtualWorldDestroy()
        self.rpc.Discard()
        del self.rpc
        super(VirtualModuleClient, self).OnDestroy()

    def ConfigEvent(self):
        super(VirtualModuleClient, self).ConfigEvent()
        self.defaultEvent.update({
            ClientEvent.OnKeyPressInGame: self.OnKeyPressInGame,
            ClientEvent.OnScriptTickClient: self.OnScriptTickClient,
            ClientEvent.GetEntityByCoordEvent: self.GetEntityByCoordEvent,
            ClientEvent.MouseWheelClientEvent: self.MouseWheelClientEvent,
            ClientEvent.ClientPlayerInventoryOpenEvent: self.ClientPlayerInventoryOpenEvent,
        })

    # -----------------------------------------------------------------------------------
    @property
    def server(self):
        # type: () -> VirtualModuleServer
        return self.rpc

    # -----------------------------------------------------------------------------------

    """接口相关"""

    # 设置虚拟世界显示
    def SetVisible(self, visible):
        # type: (bool) -> None
        """设置虚拟世界显示"""
        if self.is_visible == visible:
            return
        self.is_visible = visible
        self.virtual_comp.VirtualWorldToggleVisibility(self.is_visible)

    # -----------------------------------------------------------------------------------

    @is_active_virtual
    def OnScriptTickClient(self):
        if self.GetKeyState(KeyBoardType.KEY_W):
            self.camera_pos[2] -= self.camera_step
        elif self.GetKeyState(KeyBoardType.KEY_S):
            self.camera_pos[2] += self.camera_step
        if self.GetKeyState(KeyBoardType.KEY_A):
            self.camera_pos[0] -= self.camera_step
        elif self.GetKeyState(KeyBoardType.KEY_D):
            self.camera_pos[0] += self.camera_step
        if self.GetKeyState(KeyBoardType.KEY_SPACE):
            self.camera_pos[1] += self.camera_step
        elif self.GetKeyState(KeyBoardType.KEY_LSHIFT):
            self.camera_pos[1] -= self.camera_step
        self.virtual_comp.CameraSetPos(tuple(self.camera_pos))

    def OnKeyPressInGame(self, args):
        screen_name, is_down, key = super(VirtualModuleClient, self).OnKeyPressInGame(args)
        if screen_name != "hud_screen" or not is_down:
            return
        if key == KeyBoardType.KEY_G:
            self.SetVisible(not self.is_visible)
        if not self.is_visible:
            return
        engine_type = "test:guard"

        if key == KeyBoardType.KEY_NUMPAD0:
            pos = self.virtual_comp.CameraGetPos()
            print tuple(map(lambda x: round(x, 2), pos))

        if key == KeyBoardType.KEY_HOME:
            self.camera_pos = [0, 0, 0]

        if key == KeyBoardType.KEY_NUMPAD5:
            self.StartCoroutine(self.ActiveScene)

        if key == KeyBoardType.KEY_J:
            print self.virtual_comp.VirtualWorldSetSkyTexture("textures/virtual_world/frame", 0)

        elif key == KeyBoardType.KEY_R:
            if engine_type not in self.entity_storage:
                print "[warn]", "无模型"
                return
            entity_id = self.entity_storage[engine_type]
            self.virtual_comp.ModelSetRot(entity_id, (0.0, 0.0, 0.0))
            self.virtual_comp.ModelRotateTo(entity_id, (0.0, 90.0, 0.0), 2.5, TimeEaseType.linear)

        elif key == KeyBoardType.KEY_V:
            if engine_type not in self.entity_storage:
                entity_id = self.virtual_comp.ModelCreateMinecraftObject(engine_type)
                self.entity_storage[engine_type] = entity_id
                self.ActiveScene()
            entity_id = self.entity_storage[engine_type]
            self.virtual_comp.ModelSetBoxCollider(entity_id, (10.0, 10.0, 10.0), (0.0, 0.0, 0.0))

            def active():
                self.virtual_comp.ModelUpdateAnimationMolangVariable(entity_id, {"variable.debug_anim": 1})
                yield 240
                self.virtual_comp.ModelUpdateAnimationMolangVariable(entity_id, {"variable.debug_anim": -1})

            self.StartCoroutine(active)

        elif key == KeyBoardType.KEY_DELETE:
            for entity_id in self.entity_storage.values():
                print entity_id, self.virtual_comp.ModelRemove(entity_id)
            self.entity_storage.clear()

    @is_active_virtual
    def GetEntityByCoordEvent(self, _):
        target_id = self.virtual_comp.CameraGetClickModel()
        # if target_id >= 0:
        #     module_pos = self.virtual_comp.ModelGetPos(target_id)
        #     self.virtual_comp.ModelMoveTo(target_id, (0, 0, -5), 0.5, TimeEaseType.in_sine)
        #     target_pos = Misc.GetPosModify(module_pos, (0, 0, -10))
        #     self.virtual_comp.CameraLookAt(target_pos, (0, 1, 0))
        # else:
        #     engine_type = "test:guard"
        #     if engine_type not in self.entity_storage:
        #         return
        #     self.virtual_comp.ModelMoveTo(self.entity_storage[engine_type], (0, 0, -10), 0.5)

    @is_active_virtual
    def MouseWheelClientEvent(self, args):
        if args["direction"] == 1:
            self.camera_step += 0.1
        else:
            self.camera_step -= 0.1
        if self.camera_step <= 0.1:
            self.camera_step = 0.1
        self.SetTipMessage("step: %s" % self.camera_step)

    def ClientPlayerInventoryOpenEvent(self, args):
        if self.is_visible:
            args["cancel"] = True

    def ActiveScene(self):
        """触发场景"""
        yield 0
        self.camera_pos = [0, 2.8, -9.4]
        # print self.virtual_comp.CameraSetPos()
